﻿/*
    This file is part of nDoctor Light

    NDoctor is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    NDoctor is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with NDoctor.  If not, see <http://www.gnu.org/licenses/>.
*/
namespace Probel.Ldoc.Services.Services
{
    using System.Collections.Generic;
    using System.IO;

    using Probel.Ldoc.Services.Dto;

    public interface IPatientService
    {
        #region Methods

        /// <summary>
        /// Analyses and list the incoherences in the database.
        /// </summary>
        /// <returns>A list of incoherences contained in the database</returns>
        IEnumerable<IncoherenceDto> AnalyseIncoherences();

        /// <summary>
        /// Binds the specified tag to the specified patient.
        /// </summary>
        /// <param name="tag">The tag.</param>
        /// <param name="patient">The  patient.</param>
        void Bind(TagDto tag, PatientCardDto patient);

        /// <summary>
        /// Binds the specified profession to the specified patient.
        /// </summary>
        /// <param name="profession">The profession.</param>
        /// <param name="patient">The patient.</param>
        void Bind(ProfessionCardDto profession, PatientCardDto patient);

        /// <summary>
        /// Binds the specified reputation to the specified patient.
        /// </summary>
        /// <param name="profession">The reputation.</param>
        /// <param name="patient">The patient.</param>
        void Bind(ReputationCardDto profession, PatientCardDto patient);

        /// <summary>
        /// Binds the specified insurance to the specified patient.
        /// </summary>
        /// <param name="insurance">The insurance.</param>
        /// <param name="patient">The  patient.</param>
        void Bind(InsuranceDto insurance, PatientCardDto patient);

        /// <summary>
        /// Binds the specified insurance to the specified patient.
        /// </summary>
        /// <param name="practice">The practice.</param>
        /// <param name="patient">The  patient.</param>
        void Bind(PracticeDto practice, PatientCardDto patientCardDto);

        /// <summary>
        /// Binds the specified doctor to the specified patient.
        /// </summary>
        /// <param name="doctor">The doctor.</param>
        /// <param name="patient">The patient.</param>
        void Bind(DoctorCardDto doctor, PatientCardDto patient);

        /// <summary>
        /// Creates the specified folder.
        /// </summary>
        /// <param name="folder">The folder.</param>
        void Create(RecordDrawerCardDto folder);

        /// <summary>
        /// Creates the specified record for the specified patient.
        /// </summary>
        /// <param name="record">The record.</param>
        /// <param name="drawer">The record drawer.</param>
        /// <param name="patient">The patient card.</param>
        void Create(RecordCardDto record, RecordDrawerCardDto drawer, PatientCardDto patient);

        /// <summary>
        /// Creates the specified patient with the minimum information.
        /// </summary>
        /// <param name="patient">The patient.</param>
        /// <returns>The id if the freshly created patient</returns>
        long Create(PatientCardDto patient);

        /// <summary>
        /// Creates the specified specialisation.
        /// </summary>
        /// <param name="specialisation">The specialisation.</param>
        void Create(SpecialisationDto specialisation);

        /// <summary>
        /// Creates the specified doctor.
        /// </summary>
        /// <param name="doctor">The doctor.</param>
        void Create(DoctorDto doctor);

        /// <summary>
        /// Creates a new tag and binds it to the specified patient.
        /// </summary>
        /// <param name="tag">The tag to create.</param>
        /// <param name="patient">The patient.</param>
        void CreateAndBind(TagDto tag, PatientCardDto patient);

        /// <summary>
        /// Creates a new profession and binds it to the specified patient.
        /// </summary>
        /// <param name="profession">The profession to create.</param>
        /// <param name="patient">The patient.</param>
        void CreateAndBind(ProfessionCardDto profession, PatientCardDto patient);

        /// <summary>
        /// Creates a new reputation and binds it to the specified patient.
        /// </summary>
        /// <param name="reputation">The reputation to create.</param>
        /// <param name="patient">The patient.</param>
        void CreateAndBind(ReputationCardDto reputation, PatientCardDto patient);

        /// <summary>
        /// Creates a new insurance and binds it to the specified patient.
        /// </summary>
        /// <param name="insurance">The insurance to create.</param>
        /// <param name="patient">The patient.</param>
        void CreateAndBind(InsuranceDto insurance, PatientCardDto patient);

        /// <summary>
        /// Creates a new practice and binds it to the specified patient.
        /// </summary>
        /// <param name="practice">The practice to create.</param>
        /// <param name="patient">The patient.</param>
        void CreateAndBind(PracticeDto practice, PatientCardDto patient);

        /// <summary>
        /// Creates a new medical record with the default configuration (the title is the date of today)
        /// </summary>
        /// <param name="recordDrawer">The record drawer od the record to create.</param>
        /// <param name="patient">The patient to whom this record will be added.</param>
        void CreateDefaultRecord(RecordDrawerDto recordDrawer, PatientCardDto patient);

        /// <summary>
        /// Adds a new macro.
        /// </summary>
        void CreateNewMacro();

        /// <summary>
        /// Checks if the specified tag exists in the repository.
        /// </summary>
        /// <param name="tag">The tag to ckeck.</param>
        /// <returns><c>True</c> if it exists; otherwise <c>False</c></returns>
        bool Exists(TagDto tag);

        /// <summary>
        /// Checks if the specified profession exists in the repository.
        /// </summary>
        /// <param name="profession">The profession to check.</param>
        /// <returns><c>True</c> if it exists; otherwise <c>False</c></returns>
        bool Exists(ProfessionCardDto profession);

        /// <summary>
        /// Checks if the specified reputation exists in the repository.
        /// </summary>
        /// <param name="reputation">The reputation to check.</param>
        /// <returns>
        ///   <c>True</c> if it exists; otherwise <c>False</c>
        /// </returns>
        bool Exists(ReputationCardDto reputation);

        /// <summary>
        /// Checks if the specified insurance exists in the repository.
        /// </summary>
        /// <param name="insurance">The insurance to check.</param>
        /// <returns>
        ///   <c>True</c> if it exists; otherwise <c>False</c>
        /// </returns>
        bool Exists(InsuranceDto insurance);

        /// <summary>
        /// Checks if the specified practice exists in the repository.
        /// </summary>
        /// <param name="practice">The practice to check.</param>
        /// <returns>
        ///   <c>True</c> if it exists; otherwise <c>False</c>
        /// </returns>
        bool Exists(PracticeDto practice);

        /// <summary>
        /// Expands the specified patient card. That's, load all the data of this patient
        /// </summary>
        /// <param name="patient">The patient.</param>
        /// <returns>THe expanded patient</returns>
        ExpandedPatientDto Expand(PatientCardDto patient);

        /// <summary>
        /// Gets the expanded card of the specified patient.
        /// </summary>
        /// <param name="patient">The patient.</param>
        /// <returns>The expanded card of the spevified patient</returns>
        ExpandedPatientCardDto ExpandCard(PatientCardDto patient);

        /// <summary>
        /// Fixes the lower case insurances.
        /// </summary>
        void FixLowerCaseInsurances();

        /// <summary>
        /// Fixes the lower case practices.
        /// </summary>
        void FixLowerCasePractices();

        /// <summary>
        /// Fixes the lower case professions.
        /// </summary>
        void FixLowerCaseProfessions();

        /// <summary>
        /// Fixes the lower case reputations.
        /// </summary>
        void FixLowerCaseReputations();

        /// <summary>
        /// Replace the insurance doubloons with the specified insurance.
        /// </summary>
        /// <param name="insurance">The insurance.</param>
        void FixSpellingInsurances(InsuranceCardDto insurance);

        /// <summary>
        /// Replace the profession doubloons with the specified profession.
        /// </summary>
        /// <param name="profession">The profession.</param>
        void FixSpellingProfessions(ProfessionCardDto profession);

        /// <summary>
        /// Replace the retputation doubloons with the specified reputation.
        /// </summary>
        /// <param name="profession">The profession.</param>
        void FixSpellingReputations(ReputationCardDto reputation);

        /// <summary>
        /// Gets all assignable tags for the spevified patient.
        /// </summary>
        /// <param name="patient">The patient.</param>
        /// <returns>
        /// All the search tags
        /// </returns>
        IEnumerable<TagDto> GetAllAssignableTags(PatientCardDto patient);

        /// <summary>
        /// Gets all insurances.
        /// </summary>
        /// <returns>All the insurances</returns>
        IEnumerable<InsuranceCardDto> GetAllInsurances();

        /// <summary>
        /// Gets all macro cards stored in the repository.
        /// </summary>
        /// <returns></returns>
        IEnumerable<MacroDto> GetAllMacro();

        /// <summary>
        /// Gets all the pictures stored in the database
        /// </summary>
        /// <returns>A list of pcictures</returns>
        IEnumerable<PictureDto> GetAllPictures();

        /// <summary>
        /// Gets all practices.
        /// </summary>
        /// <returns>All the practices</returns>
        IEnumerable<PracticeCardDto> GetAllPractices();

        /// <summary>
        /// Gets all professions.
        /// </summary>
        /// <returns>All the professions</returns>
        IEnumerable<ProfessionCardDto> GetAllProfessions();

        /// <summary>
        /// Gets all reputations.
        /// </summary>
        /// <returns>All the reputations</returns>
        IEnumerable<ReputationCardDto> GetAllReputations();

        /// <summary>
        /// Gets all specialisations from the repository.
        /// </summary>
        /// <returns>All the reputations of the repository</returns>
        IEnumerable<SpecialisationDto> GetAllSpecialisations();

        /// <summary>
        /// Gets the doctors that fulfil the criterion.
        /// </summary>
        /// <param name="criterion">The criterion.</param>
        /// <returns>The doctors that fulil the criterion</returns>
        IEnumerable<DoctorCardDto> GetDoctors(SearchCriterion criterion);

        /// <summary>
        /// Gets the first insurance with the exact same name.
        /// The search is NOT case sensitive but take into account
        /// the diatrics (ie: é,è,ç,à)
        /// </summary>
        /// <param name="name">The name.</param>
        /// <returns>The first insurance with the exact name or <c>NULL</c> if nothing is found</returns>
        InsuranceDto GetFirstInsurance(string name);

        /// <summary>
        /// Gets the first practice with the exact same name.
        /// The search is NOT case sensitive but take into account
        /// the diatrics (ie: é,è,ç,à)
        /// </summary>
        /// <param name="name">The name.</param>
        /// <returns>The first practice with the exact name or <c>NULL</c> if nothing is found</returns>
        PracticeDto GetFirstPractice(string name);

        /// <summary>
        /// Gets the history of the specified medical record.
        /// </summary>
        /// <param name="record">The record.</param>
        /// <returns>The history of the medical record</returns>
        IEnumerable<RecordStateCardDto> GetHistoryOf(RecordCardDto record);

        /// <summary>
        /// Gets the insurances to fix. This is the list of all doubloons
        /// </summary>
        /// <returns>All the insurances with doubloons</returns>
        IEnumerable<InsuranceDto> GetInsurancesDoubloons(string name);

        /// <summary>
        /// Gets the insurances to fix. That's all the insurance that have doubloons.
        /// </summary>
        /// <returns>All the insurances with doubloons</returns>
        IEnumerable<InsuranceCardDto> GetInsurancesToFix();

        /// <summary>
        /// Gets the lower cased insurances.
        /// </summary>
        /// <returns>All the lower cased insurances</returns>
        IEnumerable<string> GetLowerCasedInsurances();

        /// <summary>
        /// Gets the lower cased practices.
        /// </summary>
        /// <returns></returns>
        IEnumerable<string> GetLowerCasedPractices();

        /// <summary>
        /// Gets the lower cased professions.
        /// </summary>
        /// <returns>All the lower cased professions</returns>
        IEnumerable<string> GetLowerCasedProfessions();

        /// <summary>
        /// Gets the lower cased reputations.
        /// </summary>
        /// <returns>All the lower cased reputations</returns>
        IEnumerable<string> GetLowerCasedReputations();

        /// <summary>
        /// Gets all the macros of the specified patient.
        /// </summary>
        /// <param name="patient">The patient card dto.</param>
        /// <returns></returns>
        IEnumerable<MacroDto> GetMacros(PatientCardDto patient);

        /// <summary>
        /// Gets the patient with the specified id.
        /// </summary>
        /// <param name="id">The identifier.</param>
        /// <returns>The patient with this identifyer or null if it doesn't exist</returns>
        PatientCardDto GetPatient(long id);

        /// <summary>
        /// Gets the patients based on the specified criterion.
        /// </summary>
        /// <param name="options">The criterion of the query to execute.</param>
        /// <returns>The patient resulting the query</returns>
        IEnumerable<PatientCardDto> GetPatients(SearchCriterion options);

        /// <summary>
        /// Gets the professions to fix. This is the list of all doubloons
        /// </summary>
        /// <param name="profession">The profession.</param>
        /// <returns>
        /// All the professions with doubloons
        /// </returns>
        IEnumerable<ProfessionCardDto> GetProfessionDoubloons(string profession);

        /// <summary>
        /// Gets the professions to fix. That's all the professions that have doubloons.
        /// </summary>
        /// <returns>All the insurances with doubloons</returns>
        IEnumerable<ProfessionCardDto> GetProfessionsToFix();

        /// <summary>
        /// Gets the summary of all the medical card grouped by tags
        /// </summary>
        /// <param name="patientCardDto">The patient from which this summary is retrieved.</param>
        /// <returns>A list of tags and the medical cards linked to them</returns>
        RecordCabinetDto GetRecordsCabinet(PatientCardDto patientCardDto);

        /// <summary>
        /// Gets all the records drawers.
        /// </summary>
        /// <returns></returns>
        IEnumerable<RecordDrawerCardDto> GetRecordsDrawers();

        /// <summary>
        /// Gets the reputations to fix. This is the list of all doubloons
        /// </summary>
        /// <param name="reputation">The reputation.</param>
        /// <returns>
        /// All the reputation with doubloons
        /// </returns>
        IEnumerable<ReputationCardDto> GetReputationDoubloons(string reputation);

        /// <summary>
        /// Gets the reputations to fix. That's all the reputation that have doubloons.
        /// </summary>
        /// <returns>All the reputations with doubloons</returns>
        IEnumerable<ReputationCardDto> GetReputationsToFix();

        /// <summary>
        /// Gets text (RTF formatted) tof the specified medical record
        /// </summary>
        /// <param name="recordCard">The record card.</param>
        /// <returns>The medical record content</returns>
        string GetRtfFromRecord(RecordCardDto recordCard);

        /// <summary>
        /// Gets RTF from the specified record state.
        /// </summary>
        /// <param name="state">The state.</param>
        /// <returns></returns>
        string GetRtfFromRecordState(RecordStateCardDto state);

        /// <summary>
        /// Determines whether the specified patient has this tag.
        /// </summary>
        /// <param name="patient">The expanded patient dto.</param>
        /// <param name="tag">The tag.</param>
        /// <returns><c>True</c> if this patient has this tag. Otherwise <c>False</c></returns>
        bool HasTag(PatientCardDto patient, TagDto tag);

        /// <summary>
        /// Determines whether the specified doctor is binded to this specified patient.
        /// </summary>
        /// <param name="doctor">The doctor.</param>
        /// <param name="toThisPatient">To this patient.</param>
        /// <returns><c>True</c> if the patient has already the specified doctor. Otherwise <c>False</c></returns>
        bool IsBinded(DoctorCardDto doctor, PatientCardDto toThisPatient);

        /// <summary>
        /// Determines whether the specified macro is valid.
        /// </summary>
        /// <param name="macro">The macro.</param>
        /// <returns></returns>
        bool IsMacroValid(MacroDto macro);

        /// <summary>
        /// Get the medical record card from the specified record card.
        /// </summary>
        /// <param name="record">The record.</param>
        /// <returns>A medical record card with the fresh data retrieved from the database</returns>
        RecordCardDto RefreshCard(RecordCardDto record);

        /// <summary>
        /// Removes the specified record.
        /// </summary>
        /// <param name="record">The record to be removed.</param>
        void Remove(RecordCardDto record);

        /// <summary>
        /// Removes the specified macro.
        /// </summary>
        /// <param name="macro">The macro.</param>
        void Remove(MacroDto macro);

        /// <summary>
        /// Resolves the macro for the specified macro.
        /// </summary>
        /// <param name="script">The script.</param>
        /// <param name="patient">The patient.</param>
        /// <returns>The resolved macro as a text</returns>
        string ResolveMacro(string script, PatientCardDto patient);

        /// <summary>
        /// Saves the RTF into the specified record.
        /// </summary>
        /// <param name="record">The record.</param>
        /// <param name="rtf">The RTF.</param>
        void SaveRtf(RecordCardDto record, string rtf);

        /// <summary>
        /// Unbinds the specified tag from the specified patient.
        /// </summary>
        /// <param name="tag">The tag to unbind.</param>
        /// <param name="fromPatient">From patient.</param>
        void Unbind(TagDto tag, PatientCardDto fromPatient);

        /// <summary>
        /// Unbinds the specified doctor from the specified patient.
        /// </summary>
        /// <param name="doctor">The tag to unbind.</param>
        /// <param name="fromPatient">From patient.</param>
        void Unbind(DoctorCardDto doctor, PatientCardDto fromPatient);

        /// <summary>
        /// Updates the patient into the state of the specified patient.
        /// </summary>
        /// <param name="patient">The patient.</param>
        /// <returns>The rollbacked patient</returns>
        void Update(ExpandedPatientDto patient);

        /// <summary>
        /// Updates the specified macro.
        /// </summary>
        /// <param name="macro">The macro.</param>
        void Update(MacroDto macro);

        /// <summary>
        /// Updates the name of the record's drawer .
        /// </summary>
        /// <param name="drawer">The drawer.</param>
        void UpdateRecordDrawerName(RecordDrawerCardDto drawer);

        /// <summary>
        /// Updates the name of the specified record.
        /// </summary>
        /// <param name="record">The record.</param>
        void UpdateRecordName(RecordCardDto record);

        #endregion Methods
    }
}